package petrus.components.scroll
{




	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import pages.utils.components.AbstractComponent;
	import pages.utils.components.events.ComponentEvent;





	public class AbstractScrollArea extends AbstractComponent implements IScrollArea
	{
		protected var _content:DisplayObject;

		protected var _scrollbar:AbstractScrollBar;

		protected var _maskarea:DisplayObject;

		protected var _rangeContent:Number;

		protected var _contentResizable:Boolean;

		protected var _targetWheel:DisplayObject;


		public function AbstractScrollArea()
		{
			_targetWheel = this
			super();
		
		}


		// ==> PUBLIC FUNCTIONS



		/**
		 *
		 * @inheritDoc
		 */
		override public function resize(width:Number=0, height:Number=0):void
		{
			if (content)
			{
				
				if (_contentResizable)
				{
					if (scrollbar.orientation == ScrollBarOrientation.VERTICAL)
						content.width = width;
					if (scrollbar.orientation == ScrollBarOrientation.HORIZONTAL)
						content.height = height;
				}

				maskarea.width = width;
				maskarea.height = height;

				if (scrollbar)
				{
					//scrollbar.x = content.x + content.width;
					scrollbar.x = maskarea.x + maskarea.width;

					if (scrollbar.orientation == ScrollBarOrientation.VERTICAL)
					{

						scrollbar.resize(scrollbar.width, height);
						rangeContent = content.height - maskarea.height;
					}
					if (scrollbar.orientation == ScrollBarOrientation.HORIZONTAL)
					{
						scrollbar.resize(width, scrollbar.height);
						rangeContent = content.width - maskarea.width;
					}

					if (stage)
						_launchScrollBar();
					_scrollHandler();
				}
			}
		}


		
		/**
		 * get visibleWidth
		 *
		 * @return the height of the visible content
		 */
		public function get visibleWidth():Number
		{
			if (rangeContent < 0)
				return content.width;
			else
				return _maskarea.width;
		}


		/**
		 * get visibleHeight
		 * @return the height of the visible content
		 */
		public function get visibleHeight():Number
		{
			if (rangeContent < 0)
			{
				if (content is TextField)
					return (content as TextField).textHeight;
				else
					return content.height;
			}
			else
				return _maskarea.height;
		}


		/**
		 * get the content displayObject
		 *
		 * @return content instance
		 */
		public function get content():DisplayObject
		{
			return _content;
		}


		/**
		 * get the scrollbar displayObject
		 *
		 * @return AbstractScrollBar instance
		 */
		public function get scrollbar():AbstractScrollBar
		{
			return _scrollbar;
		}


		/**
		 * set the scrollbar displayObject
		 *
		 * @param __value AbstractScrollBar instance
		 */
		public function set scrollbar(__value:AbstractScrollBar):void
		{
			_scrollbar = __value;
		}








		/**
		 * get the maskarea displayObject
		 *
		 * @return the maskarea displayObject
		 */
		public function get maskarea():DisplayObject
		{
			return _maskarea;
		}


		/**
		 * set the maskarea displayObject
		 *
		 * @param __value the rangeContent displayObject
		 */
		public function set maskarea(__value:DisplayObject):void
		{
			_maskarea = __value;
		}







		/**
		 * get the rangeContent property
		 *
		 * @return the rangeContent value
		 */
		public function get rangeContent():Number
		{
			return _rangeContent;
		}


		/**
		 * set the rangeContent property
		 *
		 * @param __value the rangeContent value
		 */
		public function set rangeContent(__value:Number):void
		{
			_rangeContent = __value;
		}


		public function set targetWheel(value:DisplayObject):void
		{
			_targetWheel = value;
		}


		/**
		 * add a displayobject to the scrollAdrea
		 *
		 * @param __source the DisplayObject to add
		 * @param __resizable true if the content is resizable
		 *
		 * @return the content added as DisplayObject
		 */
		public function addContent(__content:DisplayObject = null, __resizable:Boolean = true):DisplayObject
		{
			_contentResizable = __resizable;
			_content = __content
			_addMask();
			return addChild(content);
		}




		/**
		 * add a scrollbar
		 *
		 * @param __scrollbar instance of AbstractScrollBar to add
		 * @param __width the scrollbar width
		 * @param __height the scrollbar height
		 * @param __handlerResizable true if the scrollbar handler must be resized
		 *
		 * @return the instance of scrollbar as DisplayObject
		 */
		public function addScroll(__scrollbar:AbstractScrollBar = null, __width:Number=10, __height:Number=10, __handlerResizable:Boolean=false):DisplayObject
		{
			if (__scrollbar != null)
			{
				scrollbar = __scrollbar;
				scrollbar.addEventListener(ComponentEvent.CHANGE , _scrollHandler)

				if (__handlerResizable)
					scrollbar.setContent(content , maskarea);

				scrollbar.resize(__width, __height);

				return addChild(scrollbar);
			}

			return null;
		}







		/**
		 * scroll to a pixel position
		 *
		 * @param __pixelValue y position to scroll to
		 * @param __useEasing perform easing or not
		 */
		public function forcePixelPos(__pixelValue:Number, __useEasing:Boolean=true):void
		{
			if (__pixelValue > rangeContent)
				__pixelValue = rangeContent;

			if (__pixelValue < 0)
				__pixelValue = 0;

			scrollbar.forcePercentPos(__pixelValue / rangeContent, __useEasing );
		}


		/**
		 * scroll to a ratio value
		 *
		 * @param __percent the ratio value
		 * @param __useEasing perform easing or not
		 */
		public function forcePercentPos(__percent:Number, __useEasing:Boolean=true):void
		{
			scrollbar.forcePercentPos(__percent , __useEasing);
		}










		/**
		 *
		 * @inheritDoc
		 */
		override public function destroy(e:Event=null):void
		{
			super.destroy(e);
			scrollbar.removeEventListener(ComponentEvent.CHANGE , _scrollHandler);

			while (numChildren)
				removeChildAt(0);
		}


		/**
		 *
		 * @inheritDoc
		 */
		override protected function _init(e:Event = null):void
		{
			super._init(e);
			_launchScrollBar();
		}


		/**
		 * add a mask to the content
		 * if the __source param is null, a rectangle shape is drawn onto the content
		 *
		 * @param source the displayobject to use as mask
		 *
		 */
		protected function _addMask(__source:DisplayObject = null):void
		{
			if (__source != null)
				maskarea = __source;
			else
				maskarea = drawShape(new Rectangle(content.x, content.y, content.width, 100), 0xFF0000);

			_setMask(addChild(maskarea));
		}


		/**
		 * scroll to the y value
		 *
		 * @param __value the y value to scroll to
		 */
		protected function _scroll(__value:Number):void
		{

			//trace("_scroll" + __value)

			if (scrollbar.orientation == ScrollBarOrientation.VERTICAL)
			{
				content.y = __value;
			}
			else if (scrollbar.orientation == ScrollBarOrientation.HORIZONTAL)
			{
				content.x = __value;
			}
		}


		// ==> PRIVATE FUNCTIONS




		/**
		 * set the mask displayobject
		 *
		 * @param source the displayobject to use as mask
		 */
		private function _setMask(source:DisplayObject):void
		{
			content.cacheAsBitmap = source.cacheAsBitmap = true;
			content.mask = source;
		}


		/**
		 * _launchScrollBar
		 */
		protected function _launchScrollBar():void
		{
			if (rangeContent <= 0)
			{
				scrollbar.disable();
				
				if (_targetWheel)_targetWheel.removeEventListener(MouseEvent.MOUSE_WHEEL, _onMouseWheel);
				else trace("[AbstractScrollArea._launchScrollBar] NO TARGET WHEEL");
			}
			else
			{
				if (_targetWheel)_targetWheel.addEventListener(MouseEvent.MOUSE_WHEEL, _onMouseWheel);
				else trace("[AbstractScrollArea._launchScrollBar] NO TARGET WHEEL");
				scrollbar.enable();
			}
		}


		/**
		 * _onMouseWheel
		 *
		 * @param e
		 */
		private function _onMouseWheel(e:MouseEvent):void
		{
			var delta:Number;
			if (e.delta > 0)
				delta = 3;
			else
				delta = -3;
			scrollbar.renderWheel(-delta);
		}




		/**
		 * _scrollHandler
		 *
		 * @param e
		 */
		protected function _scrollHandler(e:ComponentEvent = null):void
		{

			_scroll(Math.floor(- scrollbar.percent * _rangeContent));
		}
	}
}